package router

import (
	"net/http"
	"strconv"
	"strings"

	"github.com/gorilla/mux"
	shttp "github.com/swaggo/http-swagger/v2"
	"go.uber.org/zap"
	"xincan.com.cn/tarot-go/internal/components/middleware"
	"xincan.com.cn/tarot-go/internal/tarot"
)

type RouteBuilder struct {

	// baseRouter 保存原始router
	baseRouter *mux.Router

	// currentRouter 当前操作的router
	currentRouter *mux.Router

	// prefix 路由前缀
	prefix string

	// methods 路由方法
	methods []string

	// middlewares 中间件
	middlewares []mux.MiddlewareFunc
}

// NewRouteBuilder
// Title 			NewRouteBuilder
// Description   	创建路由构造器实例
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		r 			*mux.Router					原始router
// Return    		*RouteBuilder							返回路由实例
func NewRouteBuilder(r *mux.Router) *RouteBuilder {
	builder := &RouteBuilder{
		baseRouter:    r,
		currentRouter: r,
	}
	builder.Use(middleware.TracingMiddleware)
	return builder
}

// Prefix
// Title 			Prefix
// Description   	设置路由前缀
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由前缀
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) Prefix(path string) *RouteBuilder {
	newPrefix := path
	if builder.prefix != "" {
		newPrefix = builder.prefix + "/" + strings.TrimPrefix(path, "/") // 拼接前缀
	}
	return &RouteBuilder{
		baseRouter:    builder.baseRouter,
		currentRouter: builder.currentRouter,
		prefix:        newPrefix,
		methods:       builder.methods,
		middlewares:   builder.middlewares,
	}
}

// WithMethods
// Title 			WithMethods
// Description   	设置路由方法
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		methods 			...string 			路由方法
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) WithMethods(methods ...string) *RouteBuilder {
	return &RouteBuilder{
		baseRouter:    builder.baseRouter,
		currentRouter: builder.currentRouter,
		prefix:        builder.prefix,
		methods:       methods,
		middlewares:   builder.middlewares,
	}
}

// GET
// Title 			GET
// Description   	GET请求封装
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) GET(path string, handler http.Handler) *RouteBuilder {
	return builder.WithMethods(http.MethodGet).Handle(path, handler)
}

// POST
// Title 			POST
// Description   	POST请求封装
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) POST(path string, handler http.Handler) *RouteBuilder {
	return builder.WithMethods(http.MethodPost).Handle(path, handler)
}

// PUT
// Title 			PUT
// Description   	PUT请求封装
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) PUT(path string, handler http.Handler) *RouteBuilder {
	return builder.WithMethods(http.MethodPut).Handle(path, handler)
}

// DELETE
// Title 			DELETE
// Description   	DELETE请求封装
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) DELETE(path string, handler http.Handler) *RouteBuilder {
	return builder.WithMethods(http.MethodDelete).Handle(path, handler)
}

// PATCH
// Title 			PATCH
// Description   	PATCH请求封装
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) PATCH(path string, handler http.Handler) *RouteBuilder {
	return builder.WithMethods(http.MethodPatch).Handle(path, handler)
}

// WithMiddleware
// Title 			WithMiddleware
// Description   	设置中间件
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		middleware 			mux.MiddlewareFunc 	中间件
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) WithMiddleware(middleware mux.MiddlewareFunc) *RouteBuilder {
	newMiddlewares := append([]mux.MiddlewareFunc{}, builder.middlewares...)
	newMiddlewares = append(newMiddlewares, middleware)
	return &RouteBuilder{
		baseRouter:    builder.baseRouter,
		currentRouter: builder.currentRouter,
		prefix:        builder.prefix,
		methods:       builder.methods,
		middlewares:   newMiddlewares,
	}
}

// Use
// Title 			Use
// Description   	使用中间件
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		middleware 			mux.MiddlewareFunc 	中间件
func (builder *RouteBuilder) Use(middleware mux.MiddlewareFunc) {
	builder.currentRouter.Use(middleware)
}

// Handle
// Title 			Handle
// Description   	处理路由
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Param    		path 			string 					路由路径
// Param    		handler 			http.Handler 		处理函数
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) Handle(path string, handler http.Handler) *RouteBuilder {
	fullPath := builder.prefix + path
	route := builder.currentRouter.Handle(fullPath, handler)
	if len(builder.methods) > 0 {
		route.Methods(builder.methods...)
	}
	for _, m := range builder.middlewares {
		route.Handler(m(handler))
	}
	return builder
}

// SubRouter
// Title 			SubRouter
// Description   	创建子路由
// Author      		alittlexincan@163.com       			2024/07/22 11:36
// Update  			alittlexincan@163.com       			2024/07/22 11:36
// Return    		*RouteBuilder							返回路由实例
func (builder *RouteBuilder) SubRouter() *RouteBuilder {
	subRouter := builder.currentRouter.PathPrefix(builder.prefix).Subrouter()
	return &RouteBuilder{
		baseRouter:    builder.baseRouter,
		currentRouter: subRouter,
		prefix:        "",
		methods:       builder.methods,
		middlewares:   builder.middlewares,
	}
}

// Swagger
// Title    		Swagger
// Description   	设置路由为Swagger
// - 使用命令:  swag2op init -d ./cmd/tarot -g main.go -o ./api/openapi/v2 --openo ./api/openapi/v3 (此中方式有告警, 可以不用管, 也可以切换到main.go所在目录执行, 此时去掉-d参数)
// - -d 指定main.go文件所在目录, 也就是swagger info的位置
// - -g 指定main.go文件
// - -o 输出swagger v2生成文件位置
// - -openo 输出swagger v3生成文件位置
// Author      		alittlexincan@163.com         	2024/07/22 11:36
// Update  			alittlexincan@163.com         	2024/07/22 11:36
// Param    		prefix 			string 			路由前缀
// Return    		*RouteBuilder					返回路由实例
func (builder *RouteBuilder) Swagger(prefix, dir string) *RouteBuilder {
	// 初始化日志

	tarot.Logger.Info("API-V2-文档地址", zap.String("url", "http://"+tarot.App.Config.Ip+":"+strconv.Itoa(int(tarot.App.Config.Port))+"/doc/v2/swagger/index.html"))
	tarot.Logger.Info("API-V3-文档地址", zap.String("url", "http://"+tarot.App.Config.Ip+":"+strconv.Itoa(int(tarot.App.Config.Port))+"/doc/v3/swagger/index.html"))
	builder.currentRouter.PathPrefix(prefix).Handler(http.StripPrefix(prefix, http.FileServer(http.Dir(dir))))
	builder.currentRouter.PathPrefix("/doc/v2/").Handler(shttp.Handler(shttp.URL(prefix + "/v2/swagger.json"))).Methods(http.MethodGet)
	builder.currentRouter.PathPrefix("/doc/v3/").Handler(shttp.Handler(shttp.URL(prefix + "/v3/swagger.json"))).Methods(http.MethodGet)
	return builder
}
